#include <iostream>
#include <vector>
#include <random>
#include <chrono>
#include <thread>
#include <cstring>

#ifdef _WIN32
#include <windows.h>
#include <conio.h>
#else
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>
#endif

class WaterfallEffect {
private:
    int width;
    int height;
    std::vector<std::vector<char>> screen;
    std::vector<std::vector<int>> intensity;
    std::vector<int> dropX;
    std::vector<int> dropY;
    std::vector<int> dropSpeed;
    std::vector<int> dropLength;
    std::mt19937 rng;
    
    // 瀑布字符集
    const std::string waterChars = "||||||";
    const std::string splashChars = "oo*+~-=";
    
public:
    WaterfallEffect(int w = 80, int h = 24) : 
        width(w), height(h), rng(std::chrono::steady_clock::now().time_since_epoch().count()) {
        
        // 初始化屏幕缓冲区
        screen.resize(height, std::vector<char>(width, ' '));
        intensity.resize(height, std::vector<int>(width, 0));
        
        // 初始化水滴
        int numDrops = width / 3;
        for (int i = 0; i < numDrops; i++) {
            dropX.push_back(std::uniform_int_distribution<int>(0, width - 1)(rng));
            dropY.push_back(std::uniform_int_distribution<int>(-height, 0)(rng));
            dropSpeed.push_back(std::uniform_int_distribution<int>(1, 3)(rng));
            dropLength.push_back(std::uniform_int_distribution<int>(3, 8)(rng));
        }
    }
    
    void clearScreen() {
#ifdef _WIN32
        system("cls");
#else
        system("clear");
#endif
    }
    
    void hideCursor() {
#ifdef _WIN32
        CONSOLE_CURSOR_INFO cursorInfo;
        GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
        cursorInfo.bVisible = false;
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
#else
        std::cout << "\033[?25l";
#endif
    }
    
    void showCursor() {
#ifdef _WIN32
        CONSOLE_CURSOR_INFO cursorInfo;
        GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
        cursorInfo.bVisible = true;
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
#else
        std::cout << "\033[?25h";
#endif
    }
    
    void setColor(int colorCode) {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colorCode);
#else
        std::cout << "\033[" << colorCode << "m";
#endif
    }
    
    void resetColor() {
#ifdef _WIN32
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); // 白色
#else
        std::cout << "\033[0m";
#endif
    }
    
    void updateDrops() {
        // 清空屏幕缓冲区
        for (auto& row : screen) {
            std::fill(row.begin(), row.end(), ' ');
        }
        for (auto& row : intensity) {
            std::fill(row.begin(), row.end(), 0);
        }
        
        // 更新每个水滴
        for (size_t i = 0; i < dropX.size(); i++) {
            // 移动水滴
            dropY[i] += dropSpeed[i];
            
            // 如果水滴超出屏幕底部，重新开始
            if (dropY[i] > height + dropLength[i]) {
                dropY[i] = -dropLength[i];
                dropX[i] = std::uniform_int_distribution<int>(0, width - 1)(rng);
                dropSpeed[i] = std::uniform_int_distribution<int>(1, 3)(rng);
                dropLength[i] = std::uniform_int_distribution<int>(3, 8)(rng);
            }
            
            // 绘制水滴轨迹
            for (int j = 0; j < dropLength[i]; j++) {
                int y = dropY[i] - j;
                int x = dropX[i];
                
                if (y >= 0 && y < height && x >= 0 && x < width) {
                    // 根据位置选择字符
                    if (j == 0) {
                        // 水滴头部
                        screen[y][x] = '*';
                        intensity[y][x] = 10;
                    } else if (j < dropLength[i] / 2) {
                        // 水滴中部
                        screen[y][x] = 'o';
                        intensity[y][x] = 8 - j;
                    } else {
                        // 水滴尾部
                        screen[y][x] = '.';
                        intensity[y][x] = 5 - j;
                    }
                }
            }
            
            // 底部水花效果
            if (dropY[i] >= height - 2) {
                for (int splash = -2; splash <= 2; splash++) {
                    int splashX = dropX[i] + splash;
                    int splashY = height - 1;
                    
                    if (splashX >= 0 && splashX < width && 
                        std::uniform_int_distribution<int>(0, 3)(rng) == 0) {
                        screen[splashY][splashX] = '+';
                        intensity[splashY][splashX] = 3;
                    }
                }
            }
        }
    }
    
    void render() {
        // 移动光标到屏幕左上角
#ifdef _WIN32
        COORD coord = {0, 0};
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
#else
        std::cout << "\033[H";
#endif
        
        // 渲染屏幕
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                char ch = screen[y][x];
                int intense = intensity[y][x];
                
                if (ch != ' ') {
                    // 根据强度设置颜色
                    if (intense > 7) {
#ifdef _WIN32
                        setColor(15); // 亮白色
#else
                        setColor(97); // 亮白色
#endif
                    } else if (intense > 5) {
#ifdef _WIN32
                        setColor(11); // 亮青色
#else
                        setColor(96); // 亮青色
#endif
                    } else if (intense > 3) {
#ifdef _WIN32
                        setColor(9); // 亮蓝色
#else
                        setColor(94); // 亮蓝色
#endif
                    } else {
#ifdef _WIN32
                        setColor(1); // 深蓝色
#else
                        setColor(34); // 蓝色
#endif
                    }
                    std::cout << ch;
                    resetColor();
                } else {
                    std::cout << ' ';
                }
            }
            std::cout << '\n';
        }
        std::cout.flush();
    }
    
    bool kbhit() {
#ifdef _WIN32
        return _kbhit();
#else
        struct timeval tv = {0L, 0L};
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0, &fds);
        return select(1, &fds, nullptr, nullptr, &tv) > 0;
#endif
    }
    
    void run() {
        clearScreen();
        hideCursor();
        
        std::cout << "瀑布效果演示 - 按任意键退出\n";
        std::cout << "==================================\n";
        
        // 等待2秒开始
        std::this_thread::sleep_for(std::chrono::seconds(2));
        clearScreen();
        
        auto lastTime = std::chrono::steady_clock::now();
        const auto frameDuration = std::chrono::milliseconds(100); // 10 FPS
        
        while (true) {
            auto currentTime = std::chrono::steady_clock::now();
            
            if (currentTime - lastTime >= frameDuration) {
                updateDrops();
                render();
                lastTime = currentTime;
            }
            
            // 检查是否有按键
            if (kbhit()) {
                break;
            }
            
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        
        showCursor();
        clearScreen();
        std::cout << "瀑布效果结束，感谢观看！\n";
    }
};

// 简单的ASCII艺术瀑布效果（备用版本）
class SimpleWaterfall {
private:
    int width;
    int height;
    std::vector<std::string> patterns;
    
public:
    SimpleWaterfall(int w = 60, int h = 20) : width(w), height(h) {
        // 预定义瀑布图案
        patterns = {
            "    ||    ||    ||    ||    ||    ||    ||    ||    ",
            "   |||   |||   |||   |||   |||   |||   |||   |||   ",
            "  ||||  ||||  ||||  ||||  ||||  ||||  ||||  ||||  ",
            " ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ",
            "||||||||||||||||||||||||||||||||||||||||||||||||||",
            "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
            "∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩∩"
        };
    }
    
    void displayFrame(int frameOffset) {
        system("clear"); // Linux
        // system("cls"); // Windows
        
        std::cout << "\n瀑布效果 - ASCII艺术版\n";
        std::cout << "========================\n\n";
        
        for (int i = 0; i < height; i++) {
            std::string line;
            
            if (i < 3) {
                // 顶部稀疏
                line = patterns[0];
            } else if (i < 8) {
                // 中上部
                line = patterns[1];
            } else if (i < 12) {
                // 中部
                line = patterns[2];
            } else if (i < 16) {
                // 中下部
                line = patterns[3];
            } else if (i < 18) {
                // 底部密集
                line = patterns[4];
            } else {
                // 水花
                line = patterns[5 + (frameOffset % 2)];
            }
            
            // 添加动态效果
            int offset = (frameOffset + i) % 4;
            if (offset > 0 && line.length() > offset) {
                line = line.substr(offset) + line.substr(0, offset);
            }
            
            if (line.length() > width) {
                line = line.substr(0, width);
            }
            
            std::cout << line << std::endl;
        }
    }
    
    void run() {
        std::cout << "简单瀑布效果演示 - 按Ctrl+C退出\n";
        std::cout << "启动中...\n";
        std::this_thread::sleep_for(std::chrono::seconds(2));
        
        for (int frame = 0; frame < 100; frame++) {
            displayFrame(frame);
            std::this_thread::sleep_for(std::chrono::milliseconds(200));
        }
        
        std::cout << "\n瀑布效果演示结束！\n";
    }
};

int main(int argc, char* argv[]) {
    std::cout << "瀑布效果程序\n";
    std::cout << "==============\n";
    std::cout << "选择瀑布效果类型:\n";
    std::cout << "1. 动态粒子瀑布 (推荐)\n";
    std::cout << "2. 简单ASCII瀑布\n";
    std::cout << "请输入选择 (1 或 2): ";
    
    int choice = 1;
    if (argc > 1) {
        choice = std::atoi(argv[1]);
    } else {
        std::cin >> choice;
    }
    
    try {
        if (choice == 2) {
            SimpleWaterfall waterfall;
            waterfall.run();
        } else {
            // 获取终端大小（可选）
            int termWidth = 80, termHeight = 24;
            
            WaterfallEffect waterfall(termWidth, termHeight);
            waterfall.run();
        }
    } catch (const std::exception& e) {
        std::cerr << "程序运行出错: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}